﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net.Mail;
using System.Text;
using System.Threading.Tasks;

namespace KulaTools
{
    public class Email
    {

        /// <summary>
        /// Tries to send an email based on the model.The same model is returned with errors if any.
        /// </summary>
        /// <param name="Recipient">Single email or emails seperated by ";"</param>
        /// <param name="BCC">Single blind carbon copyt email or list spererated by ";"</param>
        /// <returns></returns>
        public static Models.Email Send(Models.Email emailModel)
        {
            emailModel.Errors = _sendEmail(emailModel);
            return emailModel;
        }


        /// <summary>
        /// Internal function for sending emails
        /// </summary>
        /// <param name="emailModel"></param>
        /// <returns></returns>
        private static List<string> _sendEmail(Models.Email emailModel) //string emailToList, string emailBccList, string emailFrom, string emailSubject, string emailBody, bool isBodyHTML)
        {
            List<string> errors = new List<string>();

            try
            {
                //Settings stored in web.config
                string STMTPServer = WebConfig.GetValue("EmailSMTP", "Please add 'EmailSMTP' to your appSettings in your ConfigurationManager.AppSettings config file and assign an STMP Server value");

                //If test mode is True then any To and Bcc will be overwritten by webconfig settings. Allows using real / test data withoput spamming real eamil addresses and recieving emails to a test box or boxes only
                bool EmailTestMode = Convert.ToBoolean(WebConfig.GetValue("EmailTestMode", "Please add 'EmailTestMode' with 'True' or 'False' to your appSettings in your ConfigurationManager.AppSettings config file and assign an STMP Server value"));
                string EmailTestTo = WebConfig.GetValue("EmailTestTo", "Please add 'EmailTestTo' with an email or list of emails into ConfigurationManager.AppSettings config file and assign an STMP Server value");


                MailMessage message = new MailMessage();

                // Check from, else use Default in web.config
                if (String.IsNullOrEmpty(emailModel.From))
                {
                    emailModel.From = WebConfig.GetValue("EmailDefaultFrom", "Please add 'EmailDeafultFrom' to your AppSettings in your ConfigurationManager.AppSettings config file or pass in an email to value.");
                }
                message.From = new MailAddress(emailModel.From);



                // Handles multiple email addresses - seperated by semi-colon's ";" if none only 1 result is created
                string[] emailsToAdd = emailModel.Recipient.Split(';');

                foreach (string toEmail in emailsToAdd)
                {
                    //Clean any spaces
                    string email = toEmail.Trim();
                    if (email.Length > 0)
                    {
                        message.To.Add(email);
                    }
                }



                // Blind Copy email- only get if null
                if (emailModel.BCC == null)
                {
                    emailModel.BCC = WebConfig.GetValue("EmailBCC", "Please add 'EmailBCC' to your AppSettings in your ConfigurationManager.AppSettings config file or pass in an email to value.");
                }
                if (!String.IsNullOrEmpty(emailModel.BCC))
                {

                    // Handles multiple email addresses - seperated by semi-colon's
                    string[] bccToAdd = emailModel.BCC.Split(';');

                    foreach (string bccAddress in bccToAdd)
                    {
                        // Make sure not got any empty email addresses
                        string address = bccAddress.Trim();

                        if (address.Length > 0)
                        {
                            message.Bcc.Add(address);
                        }
                    }

                }

                //Attach any files to the email
                if (emailModel.Attachmanets != null && emailModel.Attachmanets.Count > 0)
                {
                    foreach (var attachment in emailModel.Attachmanets)
                    {
                        try
                        {
                            var _att = new System.Net.Mail.Attachment(attachment.LocalFilePath);
                            message.Attachments.Add(_att);
                        }
                        catch (Exception e)
                        {
                            errors.Add(e.Message);
                        }

                    }
                }


                //Now we can compose the email
                message.Subject = emailModel.Subject;
                message.Body = emailModel.Body;
                message.IsBodyHtml = emailModel.IsHtml;
                message.Priority = emailModel.Priority;


                if (EmailTestMode)
                {
                    if (!String.IsNullOrEmpty(EmailTestTo))
                    {
                        message.To.Clear();
                        message.CC.Clear();
                        message.Bcc.Clear();

                        // Handles multiple email addresses - seperated by semi-colon's
                        string[] testToAdd = EmailTestTo.Split(';');

                        foreach (string testingEmail in emailsToAdd)
                        {
                            // Make sure not got any empty email addresses
                            string address = testingEmail.Trim();

                            if (address.Length > 0)
                            {
                                message.Bcc.Add(address);
                            }

                        }
                    }
                }


                // Instantiate a new instance of SmtpClient and Send email 
                SmtpClient client = new SmtpClient(STMTPServer);
                try
                {
                    client.Send(message);
                }
                catch (Exception e)
                {
                    errors.Add(e.Message);
                }

            }
            catch (Exception e)
            {
                errors.Add(e.Message);
            }


            return errors;
        }

        ///// <summary>
        ///// Reads the string and tries to parse it a correct list of addresses.
        ///// </summary>
        ///// <param name="emailAddress"></param>
        ///// <returns></returns>
        //private static List<string> ReticualteEmails(string emailAddress){

        //}

        /// <summary>
        /// Merges a HTML template from a local HTMl file with the variables in the KeyValuePairs and returns an email HTML body.
        /// </summary>
        /// <param name="templateFilePath">The full file path to the template</param>
        /// <param name="variables">The variables to replace. Key is the variable name, e.g. $NAME$ and the value is the replace name, e.g. Bob</param>
        /// <returns></returns>
        public static string MergeTemplateAndVariables(string fullFilePath, List<KeyValuePair<string, string>> variables)
        {
            try
            {
                string body = "";

                try
                {
                    StreamReader stream = new StreamReader(fullFilePath.Replace(@"\\", @"\"));
                    body = stream.ReadToEnd();
                    stream.Close();
                }
                catch (Exception ex)
                {
                    throw;
                }


                foreach (KeyValuePair<string, string> comparer in variables)
                {
                    body = body.Replace(comparer.Key, comparer.Value);
                }

                return body;
            }
            catch (Exception ex)
            {
                throw;
            }
        }



    }
}
